package net.lqy.aipan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.lqy.aipan.config.AccountConfig;
import net.lqy.aipan.dto.AccountFileDTO;
import net.lqy.aipan.dto.StorageDTO;
import net.lqy.aipan.enums.BizCodeEnum;
import net.lqy.aipan.enums.FolderFlagEnum;
import net.lqy.aipan.exception.BizException;
import net.lqy.aipan.mapper.AccountFileMapper;
import net.lqy.aipan.mapper.StorageMapper;
import net.lqy.aipan.model.AccountFileDO;
import net.lqy.aipan.model.StorageDO;
import net.lqy.aipan.service.StorageService;
import net.lqy.aipan.util.SpringBeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class StorageServiceImpl implements StorageService {
    @Autowired
    private StorageMapper storageMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initStorage(Long accountId) {
        StorageDO storageDO = new StorageDO();
        storageDO.setAccountId(accountId);
        storageDO.setUsedSize(0L);
        storageDO.setTotalSize(AccountConfig.DEFAULT_STORAGE_SIZE);
        storageMapper.insert(storageDO);
    }

    @Override
    public StorageDO selectByAccountId(Long accountId) {
        StorageDO storageDO = storageMapper.selectOne(new QueryWrapper<StorageDO>().eq("account_id", accountId));
        return storageDO;
    }

    @Override
    public void updateByStorageFile(AccountFileDO accountFileDO) {
        StorageDO storageDO = storageMapper.selectOne(new QueryWrapper<StorageDO>().eq("account_id", accountFileDO.getAccountId()));
        storageDO.setUsedSize(storageDO.getUsedSize() + accountFileDO.getFileSize());
        storageMapper.updateById(storageDO);
    }

    @Override
    public void assertStorageEnough(Long accountId, Long fileSize) {
        StorageDO storageDO = storageMapper.selectOne(new QueryWrapper<StorageDO>().eq("account_id", accountId));
        if (storageDO.getUsedSize() + fileSize > storageDO.getTotalSize()) {
            throw new BizException(BizCodeEnum.STORAGE_NOT_ENOUGH);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateByDelFile(ArrayList<AccountFileDO> delAccountFileDOS) {
        Long accountId = delAccountFileDOS.get(0).getAccountId();
        long totalFileSize = delAccountFileDOS.stream().filter(accountFileDO -> accountFileDO.getIsDir().equals(FolderFlagEnum.FILE.getCode()))
                .mapToLong(AccountFileDO::getFileSize).sum();
        StorageDO storageDO = storageMapper.selectOne(new QueryWrapper<StorageDO>().eq("account_id", accountId));
        storageDO.setUsedSize(storageDO.getUsedSize() - totalFileSize);
        storageMapper.updateById(storageDO);
    }

    @Override
    public void updateByCopyBatchFile(List<AccountFileDO> accountFileDOS) {
        long sumSize = accountFileDOS.stream().mapToLong(accountFileDO -> accountFileDO.getFileSize()).sum();
        assertStorageEnough(accountFileDOS.get(0).getAccountId(), sumSize);
        for (AccountFileDO accountFileDO : accountFileDOS) {
            updateByStorageFile(accountFileDO);
        }
    }
}
